/**
 ******************************************************************************
 * @file    bsp_uart.c
 * @author  Iron
 * @date    2020-01-01
 * @version v1.0
 * @brief   bsp_usart c file
 */

/* Private includes ----------------------------------------------------------*/
#include "bsp_uart.h"

/* Private typedef -----------------------------------------------------------*/
#define BSP_UART_RXFIFO_BUF_SIZE    128

typedef struct
{
    bool isfull;
    uint32_t in;
    uint32_t out;
    uint8_t  buf[BSP_UART_RXFIFO_BUF_SIZE];
} bsp_uart_rxfifo_t;

typedef struct
{
    uint32_t out;
    uint32_t buf_len;
    uint8_t  *buf;
} bsp_uart_tx_handle_t;

typedef uint32_t osEventFlagsId_t;

/* Private define ------------------------------------------------------------*/

/* UART EVENTS DEFINE */
#define BSP_UART_TXC_EVT                    (1 << 0)
#define BSP_UART_RXNE_EVT                   (1 << 4)
#define BSP_UART_RXIDLE_EVT                 (1 << 5)
#define BSP_UART_RXOV_EVT                   (1 << 6)

/* priority of an interrupt */
#define BSP_UART_IRQ_PRI  2

/* 波特率 */
#ifndef BSP_USART0_BPS
    #define BSP_USART0_BPS  9600
#endif

#ifndef BSP_USART1_BPS
    #define BSP_USART1_BPS  115200
#endif

// uart id
//#define MCU_UART0_ID
#define MCU_UART1_ID    BSP_UART0
//#define MCU_UART2_ID
#define MCU_UART3_ID    BSP_UART1

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

// uart events
static osEventFlagsId_t uart_evt_ids[BSP_UART_MAX];

// uart rxfifo
static bsp_uart_rxfifo_t uart_rxfifo[BSP_UART_MAX];

// uart txhandle
static bsp_uart_tx_handle_t uart_tx_handle[BSP_UART_MAX];

/* Private function prototypes -----------------------------------------------*/

/*----------------------------------------------------------------------------*/
static void bsp_uart_set_event_bits(osEventFlagsId_t *evt_id, uint32_t event_bits)
{
    if (evt_id != NULL)
    {
//        osEventFlagsSet(evt_id, event_bits);
    }
}

static uint32_t bsp_uart_wait_event_bits(osEventFlagsId_t *evt_id, uint32_t event_bits, uint32_t timeout_ms)
{
    uint32_t get_event_bits = 0;

    if (evt_id != NULL)
    {
//        get_event_bits = osEventFlagsWait(evt_id, event_bits, osFlagsWaitAny, BSP_OS_MS_TO_TICKS(timeout_ms));
    }

    return get_event_bits;
}

/*----------------------------------------------------------------------------*/
static int32_t bsp_uart_rxfifo_length(bsp_uart_rxfifo_t *rxfifo)
{
    int32_t len;

    if (rxfifo->isfull)
    {
        len = BSP_UART_RXFIFO_BUF_SIZE;
    }
    else if (rxfifo->in >= rxfifo->out)
    {
        len = rxfifo->in - rxfifo->out;
    }
    else
    {
        len = BSP_UART_RXFIFO_BUF_SIZE + rxfifo->in - rxfifo->out;
    }

    return len;
}

static void bsp_uart_rxfifo_push_byte(bsp_uart_rxfifo_t *rxfifo, uint8_t data)
{
    int serial_line_input_byte(unsigned char c);

    serial_line_input_byte(data);

    if (!rxfifo->isfull)
    {
        rxfifo->buf[rxfifo->in] = data;

        rxfifo->in++;

        if (rxfifo->in >= BSP_UART_RXFIFO_BUF_SIZE)
            rxfifo->in = 0;

        if (rxfifo->in == rxfifo->out)
            rxfifo->isfull = true;
    }
}

static uint8_t bsp_uart_rxfifo_pull_byte(bsp_uart_rxfifo_t *rxfifo)
{
    uint8_t temp = 0xFF;

    if (rxfifo->isfull != true && rxfifo->out == rxfifo->in)
        return temp; // empty

    temp = rxfifo->buf[rxfifo->out];

    rxfifo->out++;

    if (rxfifo->out >= BSP_UART_RXFIFO_BUF_SIZE)
        rxfifo->out = 0;

    if (rxfifo->isfull)
        rxfifo->isfull = false;

    return temp;
}

/*----------------------------------------------------------------------------*/
void UART1_IRQHandler(void)
{
    UINT8 ITFlag = UART1_GetITFlag();

    switch (ITFlag)
    {
    case UART_II_LINE_STAT:         // 线路状态错误
    {
        UINT8V line_status = UART1_GetLinSTA();

        if (line_status == STA_ERR_FIFOOV)
        {
            osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART1_ID];

            bsp_uart_set_event_bits(evt_id, BSP_UART_RXOV_EVT);    // rx over flow
        }
    }
    break;

    case UART_II_RECV_RDY:          // 数据达到设置触发点
    {
        bsp_uart_rxfifo_t *rxfifo = &uart_rxfifo[MCU_UART1_ID];
        osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART1_ID];
        UINT8V line_status;

        while (1)
        {
            line_status = UART1_GetLinSTA();

            if (!(line_status & RB_LSR_DATA_RDY))
                break;

            bsp_uart_rxfifo_push_byte(rxfifo, UART1_RecvByte());
        }

        bsp_uart_set_event_bits(evt_id, BSP_UART_RXNE_EVT);
    }
    break;

    case UART_II_RECV_TOUT:         // 接收超时，暂时一帧数据接收完成
    {
        bsp_uart_rxfifo_t *rxfifo = &uart_rxfifo[MCU_UART1_ID];
        osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART1_ID];

        while (R8_UART1_RFC)
        {
            bsp_uart_rxfifo_push_byte(rxfifo, UART1_RecvByte());
        }

        bsp_uart_set_event_bits(evt_id, BSP_UART_RXNE_EVT | BSP_UART_RXIDLE_EVT);
    }
    break;

    case UART_II_THR_EMPTY:         // 发送缓存区空，可继续发送
    {
        bsp_uart_tx_handle_t *tx_handle = &uart_tx_handle[MCU_UART1_ID];
        osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART1_ID];

        while (R8_UART1_TFC != UART_FIFO_SIZE && tx_handle->out < tx_handle->buf_len)
        {
            R8_UART1_THR = tx_handle->buf[tx_handle->out];
            tx_handle->out++;
        }

        if (tx_handle->out >= tx_handle->buf_len)
        {
            bsp_uart_set_event_bits(evt_id, BSP_UART_TXC_EVT);
        }
    }
    break;

    case UART_II_MODEM_CHG:         // 只支持串口0
        break;

    default:
        break;
    }
}

void UART3_IRQHandler(void)
{
    UINT8 ITFlag = UART3_GetITFlag();

    switch (ITFlag)
    {
    case UART_II_LINE_STAT:         // 线路状态错误
    {
        UINT8V line_status = UART3_GetLinSTA();

        if (line_status == STA_ERR_FIFOOV)
        {
            osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART3_ID];

            bsp_uart_set_event_bits(evt_id, BSP_UART_RXOV_EVT);    // rx over flow
        }
    }
    break;

    case UART_II_RECV_RDY:          // 数据达到设置触发点
    {
        bsp_uart_rxfifo_t *rxfifo = &uart_rxfifo[MCU_UART3_ID];
        osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART3_ID];
        UINT8V line_status;

        while (1)
        {
            line_status = UART3_GetLinSTA();

            if (!(line_status & RB_LSR_DATA_RDY))
                break;

            bsp_uart_rxfifo_push_byte(rxfifo, UART3_RecvByte());
        }

        bsp_uart_set_event_bits(evt_id, BSP_UART_RXNE_EVT);
    }
    break;

    case UART_II_RECV_TOUT:         // 接收超时，暂时一帧数据接收完成
    {
        bsp_uart_rxfifo_t *rxfifo = &uart_rxfifo[MCU_UART3_ID];
        osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART3_ID];

        while (R8_UART3_RFC)
        {
            bsp_uart_rxfifo_push_byte(rxfifo, UART3_RecvByte());
        }

        bsp_uart_set_event_bits(evt_id, BSP_UART_RXNE_EVT | BSP_UART_RXIDLE_EVT);
    }
    break;

    case UART_II_THR_EMPTY:         // 发送缓存区空，可继续发送
    {
        bsp_uart_tx_handle_t *tx_handle = &uart_tx_handle[MCU_UART3_ID];
        osEventFlagsId_t *evt_id = &uart_evt_ids[MCU_UART3_ID];

        while (R8_UART3_TFC != UART_FIFO_SIZE && tx_handle->out < tx_handle->buf_len)
        {
            R8_UART3_THR = tx_handle->buf[tx_handle->out];
            tx_handle->out++;
        }

        if (tx_handle->out >= tx_handle->buf_len)
        {
            bsp_uart_set_event_bits(evt_id, BSP_UART_TXC_EVT);
        }
    }
    break;

    case UART_II_MODEM_CHG:         // 只支持串口0
        break;

    default:
        break;
    }
}

/*----------------------------------------------------------------------------*/
int32_t bsp_uart_get_rxfifo_length(bsp_uart_id_t uart_id)
{
    int32_t rxfifo_len = 0;

    if (uart_id < BSP_UART_MAX)
    {
        bsp_uart_rxfifo_t *rxfifo = &uart_rxfifo[uart_id];

        if (rxfifo->in >= rxfifo->out)
        {
            rxfifo_len = rxfifo->in - rxfifo->out;
        }
        else
        {
            rxfifo_len = BSP_UART_RXFIFO_BUF_SIZE + rxfifo->in - rxfifo->out;
        }
    }

    return rxfifo_len;
}

/*----------------------------------------------------------------------------*/
int32_t bsp_uart_poll_tx(bsp_uart_id_t uart_id, uint8_t *txbuf, size_t txbuf_size, uint32_t timeout_ms)
{
    int32_t txlen = -1;

    switch (uart_id)
    {
    case MCU_UART1_ID:
        UART1_SendString(txbuf, txbuf_size);
        txlen = txbuf_size;
        break;

    case MCU_UART3_ID:
        UART3_SendString(txbuf, txbuf_size);
        txlen = txbuf_size;
        break;

    default:
        break;
    }

    return txlen;
}

/*----------------------------------------------------------------------------*/
static void __uar_tx_irq_config(bsp_uart_id_t uart_id, uint8_t status)
{
    switch (uart_id)
    {
    case MCU_UART1_ID:
        UART1_INTCfg(status, RB_IER_THR_EMPTY);
        break;

    case MCU_UART3_ID:
        UART3_INTCfg(status, RB_IER_THR_EMPTY);
        break;

    default:
        break;
    }
}


int32_t bsp_uart_irq_tx(bsp_uart_id_t uart_id, uint8_t *txbuf, size_t txbuf_size, uint32_t timeout_ms)
{
    int32_t txlen = -1;

    switch (uart_id)
    {
    case MCU_UART1_ID:
    case MCU_UART3_ID:
    {
        bsp_uart_tx_handle_t *tx_handle = &uart_tx_handle[uart_id];
        osEventFlagsId_t *evt_id = &uart_evt_ids[uart_id];
        uint32_t get_events;

        tx_handle->out = 0;
        tx_handle->buf = txbuf;
        tx_handle->buf_len = txbuf_size;

        // start tx irq
        __uar_tx_irq_config(uart_id, ENABLE);

        get_events = bsp_uart_wait_event_bits(evt_id, BSP_UART_TXC_EVT, timeout_ms);

        if (!(get_events & BSP_UART_RXNE_EVT))
        {
            // timeout
        }

        txlen = tx_handle->out;

        // stop tx irq
        __uar_tx_irq_config(uart_id, DISABLE);
    }
    break;

    default:
        break;
    }

    return txlen;
}

/*----------------------------------------------------------------------------*/
static int32_t __bsp_uart_irq_rx(osEventFlagsId_t *evt_id, bsp_uart_rxfifo_t *rxfifo, uint8_t *rxbuf, size_t rxbuf_size, uint32_t timeout_ms)
{
    int32_t rxlen, rxfifo_len;

    for (rxlen = 0; rxlen < rxbuf_size;)
    {
        rxfifo_len = bsp_uart_rxfifo_length(rxfifo);

        if (rxfifo_len <= 0)
        {
            uint32_t get_events;

            get_events = bsp_uart_wait_event_bits(evt_id, BSP_UART_RXNE_EVT, timeout_ms);

            if (!(get_events & BSP_UART_RXNE_EVT))
            {
                break; // timeout or error
            }
        }
        else
        {
            rxbuf[rxlen++] = bsp_uart_rxfifo_pull_byte(rxfifo);
        }
    }

    return rxlen;
}

int32_t bsp_uart_irq_rx(bsp_uart_id_t uart_id, uint8_t *rxbuf, size_t rxbuf_size, uint32_t timeout_ms)
{
    int32_t rxlen = -1;
    bsp_uart_rxfifo_t *rxfifo;
    osEventFlagsId_t *evt_id;

    switch (uart_id)
    {
    case MCU_UART1_ID:
    case MCU_UART3_ID:
        rxfifo = &uart_rxfifo[uart_id];
        evt_id = &uart_evt_ids[uart_id];
        rxlen = __bsp_uart_irq_rx(evt_id, rxfifo, rxbuf, rxbuf_size, timeout_ms);
        break;
    default:
        break;
    }

    return rxlen;
}

int32_t bsp_uart_config(bsp_uart_id_t uart_id, uint32_t bps)
{
    switch (uart_id)
    {
//    case MCU_UART0_ID:
//        UART0_BaudRateCfg( bps );
//        break;

    case MCU_UART1_ID:
        UART1_BaudRateCfg(bps);
        break;

//    case MCU_UART2_ID:
//        UART2_BaudRateCfg( bps );
//        break;

    case MCU_UART3_ID:
        UART3_BaudRateCfg(bps);
        break;

    default:
        break;
    }

    return 0;
}

/*----------------------------------------------------------------------------*/
/*
    UART0 > TXD0:PA14(PB7),      RXD0:PA15(PB4)
    UART1 > TXD1:PA9(PB9),       RXD1:PA8(PB8)
    UART2 > TXD2:PB23(RESET),    RXD2:PA6
    UART3 > TXD3:PA4(PB21/BOOT), RXD3:PA5(PB20)
*/
static void __uart1_init(void)
{
    GPIOPinRemap(DISABLE, RB_PIN_UART1);

    /* 配置串口1：先配置IO口模式，再配置串口 */
    GPIOA_SetBits(GPIO_Pin_9);
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);     // TXD-配置推挽输出，注意先让IO口输出高电平
    GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);          // RXD-配置上拉输入

    UART1_DefInit();

    UART1_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT);

    NVIC_SetPriority(UART1_IRQn, BSP_UART_IRQ_PRI);
    NVIC_EnableIRQ(UART1_IRQn);
}

static void __uart3_init(void)
{
    GPIOPinRemap(DISABLE, RB_PIN_UART3);

    GPIOA_SetBits(GPIO_Pin_5);
    GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeOut_PP_5mA);     // TXD-配置推挽输出，注意先让IO口输出高电平
    GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU);          // RXD-配置上拉输入

    UART3_DefInit();

    UART3_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT);

    NVIC_SetPriority(UART3_IRQn, BSP_UART_IRQ_PRI);
    NVIC_EnableIRQ(UART3_IRQn);
}

int32_t bsp_uart_init(void)
{
    bsp_uart_id_t uart_id;

    for (uart_id = BSP_UART0; uart_id < BSP_UART_MAX; uart_id ++)
    {
//        uart_evt_ids[uart_id] = osEventFlagsNew(NULL);
    }

    __uart1_init();

    __uart3_init();

    return 0;
}


/**
 * @}
 */

/******************* (C)COPYRIGHT 2020 ***** END OF FILE *********************/
